var Engine = Class.extend({
	init: function(canvas){
		this.context = new Context();
		this.context.renderer = new Renderer(canvas);
		this.context.shaderManager = new ShaderManager();
		this.context.materialManager = new MaterialManager();
		this.context.textureManager = new TextureManager();
		this.requestAnimFrame =
			//window.requestAnimationFrame || 
			//window.webkitRequestAnimationFrame || 
			//window.mozRequestAnimationFrame    || 
			//window.oRequestAnimationFrame      || 
			//window.msRequestAnimationFrame     || 
			function(updateCallback, interval, userdata){
				window.setTimeout(updateCallback, interval, userdata);
			};
		
		this.frameUpdateListeners = [];
		this.previousFrameTime = new Date();
	},

	/**
	* Registers a material with the engine.  The configuration should contain the following keys:
	* 	materialName - The name of the material to reference to later
	* 	shaderName - The name of the shader to use for this material.  The shader should be registered before calling this
	* 	textureName - The name of the texture to use with the material.  The texture should be registered before calling this
	*/
	registerMaterial: function(materialConfig) {
		this.context.materialManager.registerMaterial(this.context, materialConfig.materialName, 
				materialConfig.shaderName, materialConfig.textureName)
	},
	
	/**
	* Registers a material with the engine.  The configuration should contain the following keys:
	* 	shaderName - The name of the shader to reference to later
	* 	vertexShaderFilename - The filename of the vertex shader.  An entry for this file should be provided in the Resource Manager for prefetching
	* 	fragmentShaderFilename - The filename of the fragment shader.  An entry for this file should be provided in the Resource Manager for prefetching
	*/
	registerShader: function(shaderConfig) {
		this.context.shaderManager.registerShader(this.context, shaderConfig.shaderName, 
				shaderConfig.vertexShaderFilename, shaderConfig.fragmentShaderFilename)
	},
	
	/**
	* Registers a texture with the engine
	* 	textureName - The name of the texture to reference to later
	* 	url - source url
	*/
	registerTexture: function(textureConfig) {
		this.context.textureManager.registerTexture(this.context, textureConfig.textureName, textureConfig.url)
	},
	
	
	startRenderingLoop: function() {
		this._renderLoop(this);
	},
	
	_renderLoop: function(caller) {
		caller.updateFrame();
		//this.requestAnimFrame(caller._renderLoop, 16, caller);
		window.setTimeout(caller._renderLoop, 16, caller);
	},
	
	updateFrame: function() {
		var currentFrameTime = new Date();
		var elapsedTime = (currentFrameTime - this.previousFrameTime) / 1000.0;
		this.previousFrameTime = currentFrameTime;
		this.context.renderer.onFrameUpdate(this.context, elapsedTime);
		for (var i = 0; i < this.frameUpdateListeners.length; i++) {
			var listener = this.frameUpdateListeners[i];
			listener.onFrameUpdate(this.context, elapsedTime);
		}
	},
	
	addFrameUpdateListener: function(listener) {
		this.frameUpdateListeners.push(listener)
	}
}); 
